package com.yamaikeji.plan.controller;

import com.yamaikeji.common.annotation.Log;
import com.yamaikeji.common.core.controller.BaseController;
import com.yamaikeji.common.core.domain.AjaxResult;
import com.yamaikeji.common.enums.BusinessType;
import com.yamaikeji.plan.aop.CheckLogin;
import com.yamaikeji.system.domain.plan.Plan;
import com.yamaikeji.system.domain.plan.PlanTask;
import com.yamaikeji.system.domain.plan.Task;
import com.yamaikeji.system.service.plan.IPlanService;
import com.yamaikeji.system.service.plan.IPlanTaskService;
import com.yamaikeji.system.service.plan.ITaskService;
import com.yamaikeji.system.util.IdCreateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 计划Controller
 * 
 * @author yamaikeji
 * @date 2023-10-03
 */
@RestController
@RequestMapping("/api/plan/plan")
public class PlanController extends BaseController {

    @Autowired
    private IPlanService planService;

    @Autowired
    private IPlanTaskService planTaskService;

    @Autowired
    private ITaskService taskService;

    /**
     * 查询计划列表
     */
    @CheckLogin
    @PostMapping("/getPlanList")
    public AjaxResult getPlanList(HttpServletRequest req, @RequestBody Plan plan) {
        String userNo = (String) req.getAttribute("userNo");
        plan.setUserNo(userNo);
        startPage();
        List<Plan> list = planService.selectPlanList(plan);
        this.getPlanOtherInfo(userNo, list);
        return AjaxResult.success(list);
    }

    /**
     * 查询计划详情
     */
    @CheckLogin
    @PostMapping("/getPlan")
    public AjaxResult getPlan(HttpServletRequest req, @RequestBody Plan plan) {
        String userNo = (String) req.getAttribute("userNo");
        plan.setUserNo(userNo);
        plan = planService.selectPlan(plan);
        this.getPlanOtherInfo(userNo, Arrays.asList(plan));
        return AjaxResult.success(plan);
    }

    private void getPlanOtherInfo(String userNo, List<Plan> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (Plan p : list) {
                if (p.getTotalTaskNum() == 0) {
                    p.setPlanPeriodRate(0D);
                } else {
                    Double planPeriodRate = Double.valueOf(p.getCompleteTaskNum() / p.getTotalTaskNum());
                    p.setPlanPeriodRate(planPeriodRate);
                }
            }
            List<String> planNoList = list.stream().map(Plan::getPlanNo).collect(Collectors.toList());
            PlanTask planTask = new PlanTask();
            planTask.setUserNo(userNo);
            planTask.setPlanNoList(planNoList);
            List<PlanTask> planTaskList = planTaskService.selectPlanTaskList(planTask);
            if (CollectionUtils.isNotEmpty(planTaskList)) {
                Map<String, List<PlanTask>> planTaskMap = planTaskList.stream().collect(Collectors.groupingBy(PlanTask::getPlanNo));
                for (Plan item : list) {
                    item.setPlanTaskList(planTaskMap.get(item.getPlanNo()));
                }
            }
            Task task = new Task();
            task.setUserNo(userNo);
            task.setPlanNoList(planNoList);
            List<Task> taskList = taskService.selectTaskList(task);
            if (CollectionUtils.isNotEmpty(taskList)) {
                Map<String, List<Task>> taskMap = taskList.stream().collect(Collectors.groupingBy(Task::getPlanNo));
                for (Plan item : list) {
                    item.setTaskList(taskMap.get(item.getPlanNo()));
                }
            }
        }
    }

    /**
     * 查询计划数
     */
    @CheckLogin
    @PostMapping("/getPlanNum")
    public AjaxResult getPlanNum(HttpServletRequest req, @RequestBody Plan plan) {
        String userNo = (String) req.getAttribute("userNo");
        plan.setUserNo(userNo);
        List<Plan> planList = planService.selectPlanNum(plan);
        Map<String, Integer> planNumMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(planList)) {
            planNumMap = planList.stream().collect(Collectors.toMap(Plan::getPlanTimeType, Plan::getPlanNum));
        }
        Plan getPlan = new Plan();
        getPlan.setUserNo(userNo);
        getPlan.setPlanName(plan.getPlanName());
        getPlan.setPlanTimeType("0");
        getPlan.setNowTime(LocalDate.now());
        List<Plan> list = planService.selectPlanList(getPlan);
        getPlan = new Plan();
        getPlan.setDayPlanNum(list.size());
        getPlan.setOnePlanNum(planNumMap.get("1") != null ? planNumMap.get("1") : 0);
        getPlan.setMorePlanNum(planNumMap.get("2") != null ? planNumMap.get("2") : 0);
        getPlan.setRangePlanNum(planNumMap.get("3") != null ? planNumMap.get("3") : 0);
        getPlan.setPriedPlanNum(planNumMap.get("4") != null ? planNumMap.get("4") : 0);
        getPlan.setTotalPlanNum(getPlan.getOnePlanNum() + getPlan.getMorePlanNum() + getPlan.getRangePlanNum() + getPlan.getPriedPlanNum());
        return AjaxResult.success(getPlan);
    }

    /**
     * 新增计划
     */
    @CheckLogin
    @Log(title = "新增计划", businessType = BusinessType.INSERT)
    @PostMapping("/addPlan")
    public AjaxResult addPlan(HttpServletRequest req, @RequestBody Plan plan) {
        String planNo = IdCreateUtil.generateNo("P");
        plan.setPlanNo(planNo);
        String userNo = (String) req.getAttribute("userNo");
        plan.setUserNo(userNo);
        planService.insertPlan(plan);
        if (CollectionUtils.isNotEmpty(plan.getPlanTaskList())) {
            for (PlanTask item : plan.getPlanTaskList()) {
                item.setUserNo(userNo);
                item.setPlanTaskNo(IdCreateUtil.generateNo("PT"));
                item.setPlanNo(planNo);
            }
            planTaskService.batchInsertPlanTask(plan.getPlanTaskList());
        }
        List<Plan> planList = new ArrayList<>();
        planList.add(plan);
        taskService.createTask(planList);
        return AjaxResult.success(1);
    }

    /**
     * 修改计划
     */
    @CheckLogin
    @Log(title = "修改计划", businessType = BusinessType.UPDATE)
    @PostMapping("/editPlan")
    public AjaxResult editPlan(HttpServletRequest req, @RequestBody Plan plan) {
        String userNo = (String) req.getAttribute("userNo");
        plan.setUserNo(userNo);
        planService.updatePlan(plan);
        // 获取老数据
        PlanTask planTask = new PlanTask();
        planTask.setUserNo(userNo);
        planTask.setPlanNo(plan.getPlanNo());
        List<PlanTask> oldPlanTaskList = planTaskService.selectPlanTaskList(planTask);
        Map<String, PlanTask> oldPlanTaskMap = oldPlanTaskList.stream().collect(Collectors.toMap(PlanTask::getPlanTaskNo, item -> item));
        // 分别记录新增、删除、修改任务
        List<PlanTask> newPlanTaskList = plan.getPlanTaskList();
        List<PlanTask> addPlanTaskList = new ArrayList<>();
        List<PlanTask> updatePlanTaskList = new ArrayList<>();
        Set<String> planTaskNoList = new HashSet<>();
        for (PlanTask newPlanTask : newPlanTaskList) {
            String planTaskNo = newPlanTask.getPlanTaskNo();
            if (oldPlanTaskMap.containsKey(planTaskNo)) {
                // 修改：相同 taskNo 的任务
                updatePlanTaskList.add(newPlanTask);
                planTaskNoList.add(planTaskNo);
            } else {
                // 新增：taskNo 不存在于老数据
                addPlanTaskList.add(newPlanTask);
            }
        }
        // 删除：老数据中不存在于新数据的任务
        List<PlanTask> deletePlanTaskList = oldPlanTaskList.stream().filter(PlanTask -> !planTaskNoList.contains(PlanTask.getPlanTaskNo())).collect(Collectors.toList());
        // 执行数据库操作
        if (CollectionUtils.isNotEmpty(addPlanTaskList)) {
            for (PlanTask item : addPlanTaskList) {
                item.setPlanTaskNo(IdCreateUtil.generateNo("PT"));
                item.setPlanNo(plan.getPlanNo());
                item.setUserNo(userNo);
            }
            planTaskService.batchInsertPlanTask(addPlanTaskList);
        }
        if (CollectionUtils.isNotEmpty(deletePlanTaskList)) {
            Map<String, Object> param = new HashMap<>();
            param.put("userNo", userNo);
            param.put("list", deletePlanTaskList.stream().map(PlanTask::getPlanTaskNo).collect(Collectors.toList()));
            planTaskService.batchDeletePlanTask(param);
        }
        if (CollectionUtils.isNotEmpty(updatePlanTaskList)) {
            for (PlanTask item : updatePlanTaskList) {
                item.setUserNo(userNo);
            }
            Map<String, Object> param = new HashMap<>();
            param.put("userNo", userNo);
            param.put("list", updatePlanTaskList);
            planTaskService.batchUpdatePlanTask(param);
        }
        return AjaxResult.success(1);
    }

    /**
     * 更新使用时间
     */
    @CheckLogin
    @Log(title = "更新使用时间", businessType = BusinessType.UPDATE)
    @PostMapping("/editUseTime")
    public AjaxResult editUseTime(HttpServletRequest req, @RequestBody Plan plan) {
        String userNo = (String) req.getAttribute("userNo");
        plan.setUserNo(userNo);
        return AjaxResult.success(planService.updateUseTime(plan));
    }

    /**
     * 删除计划
     */
    @CheckLogin
    @Log(title = "删除计划", businessType = BusinessType.DELETE)
    @PostMapping( "/deletePlan")
    public AjaxResult deletePlan(HttpServletRequest req, @RequestBody Plan plan) {
        String userNo = (String) req.getAttribute("userNo");
        plan.setUserNo(userNo);
        planService.deletePlan(plan);
        Task task = new Task();
        task.setUserNo(userNo);
        task.setPlanNo(plan.getPlanNo());
        taskService.deleteTask(task);
        return AjaxResult.success(1);
    }
}
